package com.work.service.main.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.work.constant.ExceptionDescription;
import com.work.constant.TallyType;
import com.work.dto.main.*;
import com.work.entity.main.ShipBillStorage;
import com.work.entity.main.TwoStockTally;
import com.work.mapper.main.TwoStockTallyMapper;
import com.work.service.main.*;
import com.work.service.transport.ITransportService;
import com.work.vo.main.*;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 多垛理货接口实现
 *
 * @author ：dujianyu
 * @since ：Created in 2024/4/2 9:16
 */
@AllArgsConstructor
@Service
public class TwoStockTallyServiceImpl extends BaseServiceImpl<TwoStockTallyMapper, TwoStockTally> implements ITwoStockTallyService {

    private ITransportService transportService;
    private ITShipBillService itShipBillService;
    private IShipBillStorageService iShipBillStorageService;
    private ITShipBillStatusService itShipBillStatusService;
    private ITShipForecastService itShipForecastService;
    private ITallyPassService iTallyPassService;
    private ITShipBillRemarkService itShipBillRemarkService;
    private ITallyMachineService tallyMachineService;

    @Override
    public boolean submitTwoStockTally(TwoStockTallyAppSubmitDTO dto) {
        TwoStockTally entity = BeanUtil.copy(dto, TwoStockTally.class);

        if (Func.isNull(entity)) {
            throw new RuntimeException(ExceptionDescription.FUN_ERROR + "submitOneStockTally-BeanUtil.copy复制失败");
        }

        entity.setUpdateUserName(AuthUtil.getUserName());

        if (!Func.isNull(entity.getOriPackageType())) {
            entity.setOriPackageTypeName(transportService.getPackageTypeNameByCode(entity.getOriPackageType()));
        }
        if (!Func.isNull(entity.getToPackageType())) {
            entity.setToPackageTypeName(transportService.getPackageTypeNameByCode(entity.getToPackageType()));
        }

        if (!Func.isNull(entity.getId())) {
            TwoStockTally detail = detail(entity.getId());
            if (!Func.isNull(detail.getIsCheck())) {
                return saveTallyBaseInfo(entity,dto);
            }
        }

        Long newToTshipBillId = itShipBillService.addTransportBill(entity.getToTransportShipId(), entity.getToTransportBillId());
        entity.setToTBillId(newToTshipBillId);

        if (!itShipForecastService.addShipForecast(entity.getToTransportShipId())) {
            throw new RuntimeException(ExceptionDescription.DB_ERROR + "添加理货船舶信息失败");
        }

        if (!itShipBillStatusService.addTshipBillStatus(newToTshipBillId, entity.getToTransportShipId(), entity.getToTransportBillId())) {
            throw new RuntimeException(ExceptionDescription.DB_ERROR + "添加理货舱单状态失败");
        }

        entity.setOriTBillId(itShipBillService.getDetailByTransportBillId(entity.getOriTransportBillId()).getId());
        entity.setToTBillId(itShipBillService.getDetailByTransportBillId(entity.getToTransportBillId()).getId());

        entity.setCheckOriPiece(entity.getOriPiece());
        entity.setCheckOriTon(entity.getOriTon());
        entity.setCheckToPiece(entity.getToPiece());
        entity.setCheckToTon(entity.getToTon());

        if (Func.isNull(entity.getId())) {
            entity.setCreateUserName(AuthUtil.getUserName());
        }

        ShipBillStorage storage = new ShipBillStorage();
        storage.setTShipBillId(entity.getToTBillId());
        storage.setTransportBillId(dto.getToTransportBillId());
        storage.setTransportShipId(dto.getToTransportShipId());
        storage.setAreaId(dto.getToStorageAreaId());
        storage.setAreaName(dto.getToStorageAreaName());
        storage.setPositionId(dto.getToStoragePositionId());
        storage.setPositionName(dto.getToStoragePositionName());
        storage.setSpot(dto.getToSpot());
        storage.setPackageType(dto.getToPackageType());
        storage.setPackageTypeName(entity.getToPackageTypeName());
        storage.setIsActive("Y");
        storage.setActiveInfo("NORMAL");
        storage.setGoodsPositionId(dto.getToGoodsPositionId());
        storage.setAreaCode(dto.getToAreaCode());
        Long newToAffectStorageId = iShipBillStorageService.addNewShipStorage(storage);

        entity.setToStorageId(newToAffectStorageId);

        if (!Func.isNull(entity.getId())) {
            TwoStockTally oldTallyPieceTon = baseMapper.selectById(entity.getId());
            iShipBillStorageService.addStorage(oldTallyPieceTon.getOriStorageId(), oldTallyPieceTon.getOriPiece(), oldTallyPieceTon.getOriTon());
            iShipBillStorageService.subStorage(oldTallyPieceTon.getToStorageId(), oldTallyPieceTon.getToPiece(), oldTallyPieceTon.getToTon());
        }
        switch (entity.getTallyType()) {
            case TallyType.VARIOUS:
                iShipBillStorageService.subStorageWithGoodPositionId(entity.getOriStorageId(), dto.getOriPiece(), dto.getOriTon(), dto.getOriGoodsPositionId());
                iShipBillStorageService.addStorageWithGoodPositionId(entity.getToStorageId(), dto.getToPiece(), dto.getToTon(), dto.getToGoodsPositionId());
                break;
            case TallyType.TRANSFER:
                if (!Func.isNull(entity.getId())) {
                    TwoStockTally oldTallyPieceTon = baseMapper.selectById(entity.getId());
                    itShipBillStatusService.changePieceTon(TallyType.TRANSFER_OUT, TallyType.SUB, entity.getOriTBillId(), oldTallyPieceTon.getOriPiece(), oldTallyPieceTon.getOriTon());
                    itShipBillStatusService.changePieceTon(TallyType.TRANSFER_IN, TallyType.SUB, entity.getToTBillId(), oldTallyPieceTon.getToPiece(), oldTallyPieceTon.getToTon());
                }
                iShipBillStorageService.subStorageWithGoodPositionId(entity.getOriStorageId(), dto.getOriPiece(), dto.getOriTon(), dto.getOriGoodsPositionId());
                iShipBillStorageService.addStorageWithGoodPositionId(entity.getToStorageId(), dto.getToPiece(), dto.getToTon(),dto.getToGoodsPositionId());

                itShipBillStatusService.changePieceTon(TallyType.TRANSFER_OUT, TallyType.ADD, entity.getOriTBillId(), dto.getOriPiece(), dto.getOriTon());
                itShipBillStatusService.changePieceTon(TallyType.TRANSFER_IN, TallyType.ADD, entity.getToTBillId(), dto.getToPiece(), dto.getToTon());
                break;
            default:
                throw new RuntimeException(ExceptionDescription.CONSTANT_ERROR + "无法确定理货类型");
        }
        return saveTallyBaseInfo(entity, dto);
    }

    @Override
    public IPage<TwoStockTallyVO> selectTsTallyHistoryPage(IPage<TwoStockTallyVO> page, TwoStockTallySearchDTO dto) {
        if ("Y".equals(dto.getPersonal())) {
            dto.setCreateUser(AuthUtil.getUserId());
        }
        List<TwoStockTallyVO> data = baseMapper.selectTsTallyHistoryList(dto, page);
        return page.setRecords(data);
    }

    @Override
    public boolean removeTwoStockTally(Long id) {
        TwoStockTally twoStockTally = detail(id);
        if (!Func.isNull(twoStockTally.getIsCheck())) {
            throw new RuntimeException(ExceptionDescription.LOGIC_ERROR + "该工班已审核");
        }

        iShipBillStorageService.subStorage(twoStockTally.getToStorageId(), twoStockTally.getToPiece(), twoStockTally.getToTon());
        iShipBillStorageService.addStorage(twoStockTally.getOriStorageId(), twoStockTally.getOriPiece(), twoStockTally.getOriTon());

        if (twoStockTally.getTallyType().equals(TallyType.TRANSFER)) {
            itShipBillStatusService.changePieceTon(TallyType.TRANSFER_IN, TallyType.SUB, twoStockTally.getToTBillId(), twoStockTally.getToPiece(), twoStockTally.getToTon());
            itShipBillStatusService.changePieceTon(TallyType.TRANSFER_OUT, TallyType.SUB, twoStockTally.getOriTBillId(), twoStockTally.getOriPiece(), twoStockTally.getOriTon());
        }

        return super.deleteLogic(Func.toLongList(id.toString())) && iTallyPassService.removeByTallyId(id);
    }

    @Override
    public IPage<TwoStockTallyCheckVO> selectCheckPage(IPage<TwoStockTallyCheckVO> page, TwoStockTallySearchDTO dto) {
        List<TwoStockTallyCheckVO> data = baseMapper.selectCheckList(dto, page);
        return page.setRecords(data);
    }

    @Override
    public String changeIsCheck(String id) {
        TwoStockTally detail = detail(Func.toLong(id));

        TwoStockTally update = new TwoStockTally();
        update.setId(Func.toLong(id));
        if ("Y".equals(detail.getIsCheck())) {
            update.setIsCheck("N");
        } else {
            update.setIsCheck("Y");
            update.setIsEdit("N");
        }
        update.setChecker(AuthUtil.getUserId());
        update.setCheckerName(AuthUtil.getUserName());
        if (!super.saveOrUpdate(update)) {
            throw new RuntimeException(ExceptionDescription.DB_ERROR + "更新检算状态失败");
        }
        return update.getIsCheck();
    }

    @Override
    public boolean correctPieceTon(TwoStockTallyCorrectSubmitDTO dto) {
        TwoStockTally oldTally = detail(dto.getId());

        iShipBillStorageService.addStorage(oldTally.getOriStorageId(), oldTally.getCheckOriPiece(), oldTally.getOriTon());
        iShipBillStorageService.subStorage(oldTally.getOriStorageId(), dto.getCheckOriPiece(), dto.getCheckOriTon());

        iShipBillStorageService.subStorage(oldTally.getToStorageId(), oldTally.getToPiece(), oldTally.getToTon());
        iShipBillStorageService.addStorage(oldTally.getToStorageId(), dto.getCheckToPiece(), dto.getCheckToTon());

        if (Func.isNull(oldTally.getIsCheck())) {
            oldTally.setIsCheck("N");
        }
        oldTally.setCheckOriPiece(dto.getCheckOriPiece());
        oldTally.setCheckOriTon(dto.getCheckOriTon());
        oldTally.setCheckToPiece(dto.getCheckToPiece());
        oldTally.setCheckToTon(dto.getCheckToTon());
        oldTally.setCheckType(dto.getCheckType());
        oldTally.setCheckReason(dto.getCheckReason());
        oldTally.setChecker(AuthUtil.getUserId());
        oldTally.setCheckerName(AuthUtil.getUserName());
        return super.saveOrUpdate(oldTally);
    }

    @Override
    public IPage<TwoStockTallyUnlockVO> selectUnlockPage(IPage<TwoStockTallyUnlockVO> page, TwoStockTallySearchDTO dto) {
        List<TwoStockTallyUnlockVO> data = baseMapper.selectUnlockList(dto, page);
        return page.setRecords(data);
    }

    @Override
    public String changeIsEdit(String id) {
        TwoStockTally detail = detail(Func.toLong(id));

        TwoStockTally update = new TwoStockTally();
        update.setId(Func.toLong(id));
        if("Y".equals(detail.getIsCheck())) {
            throw new RuntimeException(ExceptionDescription.LOGIC_ERROR + "检算已完成");
        }
        if ("Y".equals(detail.getIsEdit()) || Func.isNull(detail.getIsEdit())) {
            update.setIsEdit("N");
        } else {
            update.setIsEdit("Y");
        }
        update.setEditChangeUser(AuthUtil.getUserId());
        update.setEditChangeUserName(AuthUtil.getUserName());
        if (!super.saveOrUpdate(update)) {
            throw new RuntimeException(ExceptionDescription.DB_ERROR + "更新可编辑状态失败");
        }
        return update.getIsEdit();
    }

    @Override
    public TwoStockTallyUnlockDetailVO selectTstDetail(TwoStockTallySearchDTO dto) {
        if (Func.isNull(dto.getId())) {
            throw new RuntimeException(ExceptionDescription.NO_PARAM + "缺少主键ID");
        }
        return baseMapper.selectTstDetail(dto);
    }

    @Override
    public TwoStockTallyShipStatCheckDetail selectShipStatCheckDetail(TwoStockTallySearchDTO dto) {
        QueryWrapper<TwoStockTally> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .select(TwoStockTally::getId,
                        TwoStockTally::getOriPiece,
                        TwoStockTally::getOriTon,
                        TwoStockTally::getCheckOriPiece,
                        TwoStockTally::getCheckOriTon,
                        TwoStockTally::getToPiece,
                        TwoStockTally::getToTon,
                        TwoStockTally::getCheckToPiece,
                        TwoStockTally::getCheckToTon,
                        TwoStockTally::getCheckType,
                        TwoStockTally::getCheckReason)
                .eq(TwoStockTally::getIsDeleted, 0)
                .eq(TwoStockTally::getId, dto.getId())
                .last("limit 1");
        TwoStockTally entity = baseMapper.selectOne(queryWrapper);
        if (Func.isNull(entity)) {
            throw new RuntimeException(ExceptionDescription.DB_ERROR + "没有理货数据");
        }
        return BeanUtil.copy(entity, TwoStockTallyShipStatCheckDetail.class);
    }

    @Override
    public IPage<TwoStockTallySearchExportVO> selectTallySearchExportPage(IPage<TwoStockTallySearchExportVO> page, TwoStockTallySearchDTO dto) {
        List<TwoStockTallySearchExportVO> data = baseMapper.selectTallySearchExportList(dto, page);
        return page.setRecords(data);
    }

    @Override
    public TotalPieceTonVO selectTallySearchExportTotal(TwoStockTallySearchDTO dto) {
        return baseMapper.selectTallySearchExportTotal(dto);
    }

    @Override
    public IPage<TransferStatVO> selectTransferStatPage(IPage<TransferStatVO> page, TwoStockTallySearchDTO dto) {
        List<TransferStatVO> data = baseMapper.selectTransferStatList(dto, page);
        return page.setRecords(data);
    }

    @Override
    public PieceTonVO selectTransferStatTotal(TwoStockTallySearchDTO dto) {
        return baseMapper.selectTransferStatTotal(dto);
    }

    private boolean saveTallyBaseInfo(TwoStockTally entity, TwoStockTallyAppSubmitDTO dto) {
        if (!super.saveOrUpdate(entity)) {
            throw new RuntimeException(ExceptionDescription.DB_ERROR + "保存多垛理货失败");
        }
        return iTallyPassService.submitTallyPass(setTallyPassSubmitDTO(entity, dto))
                && itShipBillRemarkService.submitShipBillRemark(setTshipBillRemarkSubmitDTO(entity, dto))
                && tallyMachineService.submitTallyMachineBatch(entity.getId(), dto.getMachineList());
    }

    private TallyPassSubmitDTO setTallyPassSubmitDTO(TwoStockTally twoStockTally, TwoStockTallyAppSubmitDTO dto) {
        TallyPassSubmitDTO submitDTO = new TallyPassSubmitDTO();
        submitDTO.setTallyId(twoStockTally.getId());
        submitDTO.setTShipBillId(twoStockTally.getOriTBillId());
        submitDTO.setTransportBillId(twoStockTally.getOriTransportBillId());
        submitDTO.setTransportShipId(twoStockTally.getOriTransportShipId());
        submitDTO.setKeeper(dto.getKeeper());
        submitDTO.setKeeperName(dto.getKeeperName());
        submitDTO.setIsBedding(dto.getIsBedding());
        submitDTO.setIsCover(dto.getIsCover());
        submitDTO.setIsSafeProduction(dto.getIsSafeProduction());
        return submitDTO;
    }

    private TShipBillRemarkSubmitDTO setTshipBillRemarkSubmitDTO(TwoStockTally twoStockTally, TwoStockTallyAppSubmitDTO dto) {
        TShipBillRemarkSubmitDTO submitDTO = new TShipBillRemarkSubmitDTO();
        submitDTO.setRemark(dto.getShipBillRemark());
        submitDTO.setTShipBillId(twoStockTally.getOriTBillId());
        submitDTO.setTransportBillId(twoStockTally.getOriTransportBillId());
        submitDTO.setTransportShipId(twoStockTally.getOriTransportShipId());
        return submitDTO;
    }

    private TwoStockTally detail(Long twoStockTallyId) {
        QueryWrapper<TwoStockTally> oldTallyQuery = new QueryWrapper<>();
        oldTallyQuery.lambda()
                .eq(TwoStockTally::getId, twoStockTallyId)
                .eq(TwoStockTally::getIsDeleted, 0)
                .last("limit 1");
        TwoStockTally twoStockTally = baseMapper.selectOne(oldTallyQuery);
        if (Func.isNull(twoStockTally)) {
            throw new RuntimeException(ExceptionDescription.DB_ERROR + "多垛理货记录不存在");
        }
        return twoStockTally;
    }
}
